﻿using MarriageFertility.Actions;
using MarriageFertility.DataType;
using MarriageFertility.Dialogs;
using MarriageFertility.Extensions;
using MarriageFertility.Texts;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;

namespace MarriageFertility.Behaviors
{
    public class NtrBehavior : CampaignBehaviorBase
    {
        public override void RegisterEvents()
        {
            CampaignEvents.DailyTickEvent.AddNonSerializedListener(this, WifeLeaveLord);
            CampaignEvents.HourlyTickEvent.AddNonSerializedListener(this, UpdateWifeMoodAndEvents);
        }

        private void WifeLeaveLord()
        {
            if (NtrDialog.NtrWifeList == null || NtrDialog.NtrWifeList.Count == 0 || MobileParty.MainParty?.MemberRoster == null)
                return;

            var relationsReadyToLeave = NtrDialog.NtrWifeList
                .FindAll(relation => ShouldWifeReturn(relation));

            if (relationsReadyToLeave.Count == 0) return;

            relationsReadyToLeave.ForEach(relation =>
            {
                WifeReturnPlayer(relation);
                NtrDialog.NtrWifeList.Remove(relation);
            });
        }

        private bool ShouldWifeReturn(NtrRelation relation)
        {
            var daysPassed = (CampaignTime.Now - relation.NtrTime).ToDays;
            var playerCharm = Hero.MainHero.GetSkillValue(DefaultSkills.Charm);
            var returnChance = relation.WifeMood < 30f ? 0.7f : 0.3f;
            return daysPassed >= 1 && (MBRandom.RandomFloat < returnChance || playerCharm > 200);
        }

        private void WifeReturnPlayer(NtrRelation relation)
        {
            var (lord, wife) = (relation.Lord, relation.Wife);
            if (lord == null || wife == null) return;

            RemoveWifeFromLordParty(lord, wife);

            if (!wife.IsPregnant && MBRandom.RandomFloat < 0.3f)
            {
                RecordPregnancy(wife, lord);
                ShowMessage(wife, lord);
            }

            if (relation.WifeLoyalty < 20f && MBRandom.RandomFloat < 0.5f)
            {
                wife.ChangeState(Hero.CharacterStates.Fugitive);
                var message = NtrText.WifeLeftPermanently;
                message.SetTextVariable("wife", wife.Name);
                message.SetTextVariable("lord", lord.Name);
                MBInformationManager.AddQuickInformation(message);
                return;
            }

            if (relation.WifeLoyalty < 10f && MBRandom.RandomFloat < 0.2f)
            {
                DivorceAction.Apply(wife, Hero.MainHero);
                var divorceMessage = NtrText.WifeDivorced;
                divorceMessage.SetTextVariable("wife", wife.Name);
                MBInformationManager.AddQuickInformation(divorceMessage);
                return;
            }

            if (relation.LordLikesWife)
            {
                ChangeRelationAction.ApplyPlayerRelation(lord, 10);
            }
            else
            {
                ChangeRelationAction.ApplyPlayerRelation(lord, -5);
            }

            Hero.MainHero.Clan.Renown -= 3f;
            Hero.MainHero.Clan.Influence -= 5f;
            MBInformationManager.AddQuickInformation(NtrText.AdditionalPenalty);

            TeleportHeroAction.ApplyImmediateTeleportToParty(wife, MobileParty.MainParty);
            ChangeRelationAction.ApplyPlayerRelation(wife, -5);
        }

        private void UpdateWifeMoodAndEvents()
        {
            foreach (var relation in NtrDialog.NtrWifeList)
            {
                relation.WifeMood -= relation.LordLikesWife ? 0.5f : 1.5f;
                relation.WifeLoyalty -= 0.2f;
                
                if (CampaignTime.Now.ToHours % 12 == 0)
                {
                    relation.UpdateLordPreference();
                }

                if (MBRandom.RandomFloat < 0.05f)
                    TriggerRandomEvent(relation);
            }
        }

        private void TriggerRandomEvent(NtrRelation relation)
        {
            int eventType = MBRandom.RandomInt(3); 
            switch (eventType)
            {
                case 0: 
                    if (relation.LordLikesWife && relation.WifeMood > 70f)
                    {
                        relation.WifeLoyalty -= 20f;
                        var message = NtrText.WifeFallsForLord;
                        message.SetTextVariable("wife", relation.Wife.Name);
                        message.SetTextVariable("lord", relation.Lord.Name);
                        MBInformationManager.AddQuickInformation(message);
                    }
                    break;
                case 1: 
                    relation.NtrTime = CampaignTime.Now;
                    var demandMessage = NtrText.LordDemandsMoreTime;
                    demandMessage.SetTextVariable("lord", relation.Lord.Name);
                    demandMessage.SetTextVariable("wife", relation.Wife.Name);
                    MBInformationManager.AddQuickInformation(demandMessage);
                    break;
                case 2: 
                    if (relation.LordLikesWife && relation.WifeMood > 60f && MBRandom.RandomFloat < 0.4f)
                    {
                        if (!relation.Wife.IsSexFriend(relation.Lord))
                        {
                            relation.Wife.BecomeSexFriend(relation.Lord);
                            relation.WifeLoyalty -= 15f;
                            var sexFriendMessage = NtrText.BecomeSexFriends;
                            sexFriendMessage.SetTextVariable("wife", relation.Wife.Name);
                            sexFriendMessage.SetTextVariable("lord", relation.Lord.Name);
                            MBInformationManager.AddQuickInformation(sexFriendMessage);
                        }
                    }
                    break;
            }
        }

        private void RemoveWifeFromLordParty(Hero lord, Hero wife)
        {
            if (lord?.PartyBelongedTo?.MemberRoster?.Contains(wife.CharacterObject) == true)
            {
                lord.PartyBelongedTo.MemberRoster.AddToCounts(wife.CharacterObject, -1);
            }
        }

        private static void RecordPregnancy(Hero wife, Hero lord)
        {
            var pregnancyBehavior = Campaign.Current.GetCampaignBehavior<CustomerPregnancyCampaignBehavior>();
            pregnancyBehavior.RecordPregnancyData(wife, lord);
        }

        private static void ShowMessage(Hero wife, Hero lord)
        {
            var message = NtrText.NtrPregnancyMessage;
            message.SetTextVariable("wife", wife.Name);
            message.SetTextVariable("lord", lord.Name);
            MBInformationManager.AddQuickInformation(message);
        }

        public override void SyncData(IDataStore dataStore)
        {
            dataStore.SyncData("ntrWifeList", ref NtrDialog.NtrWifeList);
            HeroExtension.SyncData(dataStore);
        }
    }
}